package com.taotao.jul;

import org.junit.Test;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.*;

public class JulTest {
    /**
     * 基本使用
     */
    @Test
    public void test01() {
        // 只能通过getLogger获取对象 形参为当前类的全路径
        Logger logger = Logger.getLogger("com.taotao.jul.JulTest");

        logger.info("xiba lama");
        logger.log(Level.INFO, "xiba lama");

        // 通过数组下标 拼接字符串内容
        logger.log(Level.INFO, "one:{0} two:{1}", new String[]{"1", "2"});
    }

    // 日志等级
    @Test
    public void test02() {
        Logger logger = Logger.getLogger("com.taotao.jul.JulTest");

        logger.setLevel(Level.INFO);
        logger.severe("severe信息");
        logger.warning("warning信息");
        logger.info("info信息");
        logger.config("config信息");
        logger.fine("fine信息");
        logger.finer("finer信息");
        logger.finest("finest信息");
    }

    @Test
    public void test03(){
        Logger logger = Logger.getLogger("com.taotao.jul.JulTest");

        // 设置不按照父logger默认方式
        logger.setUseParentHandlers(false);

        // 设置打印到控制台处理器和普通日志格式
        ConsoleHandler handler = new ConsoleHandler();
        SimpleFormatter formatter = new SimpleFormatter();
        handler.setFormatter(formatter);
        logger.addHandler(handler);

        // 设置日志对象和处理器的打印级别
        logger.setLevel(Level.ALL);
        handler.setLevel(Level.ALL);

        logger.severe("severe信息");
        logger.warning("warning信息");
        logger.info("info信息");
        logger.config("config信息");
        logger.fine("fine信息");
        logger.finer("finer信息");
        logger.finest("finest信息");
    }

    @Test
    public void test04() throws IOException {
        Logger logger = Logger.getLogger("com.taotao.jul.JulTest");
        logger.setUseParentHandlers(false);

        // 设置将日志输出到文件的处理器
        FileHandler handler = new FileHandler("C:\\test\\myLogTest.log");
        SimpleFormatter formatter = new SimpleFormatter();
        handler.setFormatter(formatter);
        logger.addHandler(handler);

        // 同时设置在控制台打印的处理器
        ConsoleHandler handler2 = new ConsoleHandler();
        handler2.setFormatter(formatter);
        logger.addHandler(handler2); // 可以在记录器中同时添加多个处理器

        logger.setLevel(Level.ALL);
        handler.setLevel(Level.ALL);
        handler2.setLevel(Level.CONFIG);

        logger.severe("severe信息");
        logger.warning("warning信息");
        logger.info("info信息");
        logger.config("config信息");
        logger.fine("fine信息");
        logger.finer("finer信息");
        logger.finest("finest信息");
    }

    @Test
    public void test05(){
        /*
            Logger之间的父子关系
                JUL中Logger之间是存在"父子"关系的
                值得注意的是，这种父子关系不是我们普遍认为的类之间的继承关系
                关系是通过树状结构存储的

                JUL在初始化时会创建一个顶层RootLogger作为所有Logger的父Logger
                查看源码：
                    owner.rootLogger = owner.new RootLogger();
                    RootLogger是LogManager的内部类
                    java.util.logging.LogManager$RootLogger
                    默认的名称为 空串

                以上的RootLogger对象作为树状结构的根节点存在的
                将来自定义的父子关系通过路径来进行关联
                父子关系，同时也是节点之间的挂载关系
                owner.addLogger(owner.rootLogger);
                LoggerContext cx = getUserContext(); //LoggerContext一种用来保存节点的Map关系

                private LogNode               node; //节点
         */
        // Father
        Logger father = Logger.getLogger("jul");
        // Son
        Logger son = Logger.getLogger("com.taotao.jul.JulTest");

        System.out.println(son.getParent() == father); // true
        System.out.println("logger1的父Logger引用为:" + father.getParent()
                + "; 名称为" + father.getName() + "; 父亲的名称为" + father.getParent().getName());
        System.out.println("logger2的父Logger引用为:" + son.getParent()
                + "; 名称为" + son.getName() + "; 父亲的名称为" + son.getParent().getName());

        // Father做的日志相关设置会影响到Son
        father.setUseParentHandlers(false);
        ConsoleHandler handler = new ConsoleHandler();
        SimpleFormatter formatter = new SimpleFormatter();
        handler.setFormatter(formatter);
        father.addHandler(handler);
        handler.setLevel(Level.INFO);
        father.setLevel(Level.INFO);

        son.severe("severe信息");
        son.warning("warning信息");
        son.info("info信息");
        son.config("config信息");
        son.fine("fine信息");
        son.finer("finer信息");
        son.finest("finest信息");
    }

    @Test
    public void test06() throws Exception {
        /*
            以上所有的配置相关的操作，都是以java硬编码的形式进行的
            我们可以使用更加清晰，更加专业的一种做法，就是使用配置文件
            如果我们没有自己添加配置文件，则会使用系统默认的配置文件
            这个配置文件：
                owner.readPrimordialConfiguration();
                readConfiguration();
                java.home --> 找到jre文件夹 --> lib --> logging.properties

            做文件日志打印，新日志会覆盖掉原来的日志
            但是我们现在的需求不是覆盖，而是追加
         */
        InputStream input = new FileInputStream("C:\\test\\logging.properties");

        // 取得日志管理器对象
        LogManager logManager = LogManager.getLogManager();
        // 读取自定义的配置文件
        logManager.readConfiguration(input);

        Logger logger = Logger.getLogger("com.taotao.jul.JulTest");
        logger.severe("severe信息");
        logger.warning("warning信息");
        logger.info("info信息");
        logger.config("config信息");
        logger.fine("fine信息");
        logger.finer("finer信息");
        logger.finest("finest信息");
        /*
            JUL日志框架使用方式总结（原理解析）
                1.初始化LogManager
                    LogManager加载logging.properties配置文件
                    添加Logger到LogManager
                2.从单例的LogManager获取Logger
                3.设置日志级别Level，在打印的过程中使用到了日志记录的LogRecord类
                4.Filter作为过滤器提供了日志级别之外更细粒度的控制
                5.Handler日志处理器，决定日志的输出位置，例如控制台、文件...
                6.Formatter是用来格式化输出的
         */
    }
}
